package com.rdb.mbean;

import com.rdb.entities.*;
import com.rdb.mbean.util.JsfUtil;
import com.rdb.mbean.util.PaginationHelper;
import com.rdb.sbean.GroupsFacade;
import com.rdb.sbean.SubjectsFacade;
import com.rdb.sbean.UsersFacade;

import java.io.Serializable;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;

@ManagedBean(name = "usersController")
@SessionScoped
public class UsersController implements Serializable {

    public static final String AUTH_KEY = "app.user.name";
    public static final String AUTH_KEY_FULLNAME = "app.user.fullname";
    private Users current;
    private Users userSubj;
    private DataModel items = null;
    @EJB
    private com.rdb.sbean.UsersFacade ejbFacade;
    @EJB
    private com.rdb.sbean.GroupsFacade ejbGroupsFacade;
    
    @EJB
    private com.rdb.sbean.SubjectsFacade ejbSubjectsFacade;
    
    private List<Subjects> listSubject; 
    private Subjects[] listSubjectSelected; 
    private PaginationHelper pagination;
    private int selectedItemIndex;
    private String username = "";
    private String password = "";
    private String confirmPass = "";
    private String newPass = "";
    private String oldPass = "";
    private Users userLogin;
    public String getUsername() {
        return username;
    }

    public Users getUserSubj() {
        return userSubj;
    }

    public void setUserSubj(Users userSubj) {
        this.userSubj = userSubj;
    }

    public Subjects[] getListSubjectSelected() {
        return listSubjectSelected;
    }

    public void setListSubjectSelected(Subjects[] listSubjectSelected) {
        this.listSubjectSelected = listSubjectSelected;
    }

    
    public List<Subjects> getListSubject() {
        return listSubject;
    }

    public void setListSubject(List<Subjects> listSubject) {
        this.listSubject = listSubject;
    }
    
    
    public String getConfirmPass() {
        return confirmPass;
    }

    public void setConfirmPass(String confirmPass) {
        this.confirmPass = confirmPass;
    }

    public Users getUserLogin() {
        return userLogin;
    }

    public void setUserLogin(Users userLogin) {
        this.userLogin = userLogin;
    }

    public SubjectsFacade getEjbSubjectsFacade() {
        return ejbSubjectsFacade;
    }

    public void setEjbSubjectsFacade(SubjectsFacade ejbSubjectsFacade) {
        this.ejbSubjectsFacade = ejbSubjectsFacade;
    }
    
    public String getNewPass() {
        return newPass;
    }

    public void setNewPass(String newPass) {
        this.newPass = newPass;
    }

    public String getOldPass() {
        return oldPass;
    }

    public void setOldPass(String oldPass) {
        this.oldPass = oldPass;
    }

    public GroupsFacade getEjbGroupsFacade() {
        return ejbGroupsFacade;
    }

    public void setEjbGroupsFacade(GroupsFacade ejbGroupsFacade) {
        this.ejbGroupsFacade = ejbGroupsFacade;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public UsersController() {
    }

    public Users getSelected() {
        if (current == null) {
            current = new Users();
        }
        return current;
    }

    public List<Groups> getListCourse() {
        return ejbGroupsFacade.findAll();
    }

    public void setSelected(Users selected) {
        this.current = selected;
    }

    private UsersFacade getFacade() {
        return ejbFacade;
    }
    
    public List<Users> getFaculties(){
        return ejbFacade.getfaculty();
    }

    public PaginationHelper getPagination() {
        if (pagination == null) {
            pagination = new PaginationHelper(10) {
                @Override
                public int getItemsCount() {
                    return getFacade().count();
                }

                @Override
                public DataModel createPageDataModel() {
                    return new ListDataModel(getFacade().findAll());
                }
            };
        }
        return pagination;
    }

    public String prepareList() {
        recreateModel();
        return "List";
    }
    
    public String prepareList1() {
        recreateModel();
        return "/faces/admin/users/List.xhtml";
    }

    public String prepareView() {
        if (current != null) {
            return "View";
        } else {
            return prepareList();
        }
    }

    public String prepareAddSubject(){
        listSubject = ejbSubjectsFacade.findAll();
        
        List<Subjects> selList = new ArrayList<Subjects>();
        for (int i = 0; i < listSubject.size(); i++) {
            if(listSubject.get(i).getUsersList().contains(userSubj)){
                selList.add(listSubject.get(i));
            }
        }
        
        System.out.print(userSubj.getUsername() + " " + selList.size());
        listSubjectSelected = new Subjects[selList.size()];
        for (int i = 0; i < selList.size(); i++) {
            listSubjectSelected[i] = selList.get(i);
        }
        return "AddSubject";
    }
    
    public String addSubject(){
        try {
            listSubject = ejbSubjectsFacade.findAll();
            List<Subjects> selList = new ArrayList<Subjects>();
            for (int i = 0; i < listSubject.size(); i++) {
                if(listSubject.get(i).getUsersList().contains(userSubj)){
                    selList.add(listSubject.get(i));
                }
            }
            
            for (int i = 0; i < listSubjectSelected.length; i++) {
                boolean check = false;
                for (int j = 0; j < selList.size(); j++) {
                    if(listSubjectSelected[i].getId() == selList.get(j).getId())
                    {
                        check = true;
                        break;
                    }
                }
                if(!check){
                    List<Users> listUserses = listSubjectSelected[i].getUsersList();
                    listUserses.add(userSubj);
                    listSubjectSelected[i].setUsersList(listUserses);
                    ejbSubjectsFacade.edit(listSubjectSelected[i]);
                }
            }
            
            for (int i = 0; i < selList.size(); i++) {
                boolean check = false;
                for (int j = 0; j < listSubjectSelected.length; j++) {
                    if(listSubjectSelected[j].getId() == selList.get(i).getId())
                    {
                        check = true;
                        break;
                    }
                }
                if(!check){
                    List<Users> listUserses = selList.get(i).getUsersList();
                    listUserses.remove(userSubj);
                    selList.get(i).setUsersList(listUserses);
                    ejbSubjectsFacade.edit(selList.get(i));
                }
            }
            
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("bundle/Bundle").getString("UsersUpdated"));
            return "ListSubject";
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("bundle/Bundle").getString("PersistenceErrorOccured"));
            return null;
        }
        
    }
    
    public String prepareChangePass() {
        confirmPass = "";
        oldPass = "";
        newPass = "";
        return "/faces/admin/users/ChangePass.xhtml?faces-redirect=true";
    }

    public String prepareCreate() {
        current = new Users();
        confirmPass = "";
        return "Create";
    }
    
    public String prepareCreate1() {
        current = new Users();
        confirmPass = "";
        return "/faces/admin/users/Create.xhtml?faces-redirect=true";
    }

    public Users getUserL(){
        if (FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(AUTH_KEY) != null) {
           return ejbFacade.getUserByUsername(FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(AUTH_KEY).toString());
        }else{
            return null;
        }
    }
    
    public String changePass() {
        if (FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(AUTH_KEY) != null) {
            userLogin= ejbFacade.getUserByUsername(FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(AUTH_KEY).toString());
        }
        if(userLogin == null ){
            System.out.print("null");
            return null;
        }
        
        System.out.print(userLogin.getFirstName() + " " + userLogin.getLastName());
        if (!hashPassword(oldPass).equals(userLogin.getPassword())) {
            JsfUtil.addErrorMessage("Password is not correct.");
            return null;
        }
        if (newPass.equals("")) {
            JsfUtil.addErrorMessage("New Password can't empty.");
            return null;
        }

        if (!newPass.equals(confirmPass)) {
            JsfUtil.addErrorMessage("Confirm new password invalid.");
            return null;
        }
        userLogin.setPassword(hashPassword(newPass));
        try {
            getFacade().edit(userLogin);
            newPass = "";
            oldPass = "";
            confirmPass= "";
            JsfUtil.addSuccessMessage("User was successfully changed password.");
            return "ChangePass";
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("bundle/Bundle").getString("PersistenceErrorOccured"));
            return null;
        }
    }

    public String create() {
        try {
            if (current.getUsername().equals("")) {
                JsfUtil.addErrorMessage("Username can't empty.");
                return null;
            }

            for (int i = 0; i < ejbFacade.findAll().size(); i++) {
                if (current.getUsername().equals(ejbFacade.findAll().get(i).getUsername())) {
                    JsfUtil.addErrorMessage("Username is existed.");
                    return null;
                }
            }

            if (current.getPassword().equals("")) {
                JsfUtil.addErrorMessage("Password can't empty.");
                return null;
            }

            if (!current.getPassword().equals(confirmPass)) {
                JsfUtil.addErrorMessage("Confirm password invalid.");
                return null;
            }

            current.setPassword(hashPassword(current.getPassword()));

            getFacade().create(current);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("bundle/Bundle").getString("UsersCreated"));
            return prepareCreate();
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("bundle/Bundle").getString("PersistenceErrorOccured"));
            return null;
        }
    }

    public String prepareEdit() {
        return "Edit";
    }

    public String update() {
        try {
            getFacade().edit(current);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("bundle/Bundle").getString("UsersUpdated"));
            return prepareList();
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("bundle/Bundle").getString("PersistenceErrorOccured"));
            return null;
        }
    }

    public String destroy() {
        performDestroy();
        recreateModel();
        return prepareList();
    }

    public String destroyAndView() {
        performDestroy();
        recreateModel();
        setSelected(new Users());
        return "List";
    }

    private void performDestroy() {
        try {
            getFacade().remove(current);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("bundle/Bundle").getString("UsersDeleted"));
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("bundle/Bundle").getString("PersistenceErrorOccured"));
        }
    }

    public DataModel getItems() {
        if (items == null) {
            items = getPagination().createPageDataModel();
        }
        return items;
    }

    private void recreateModel() {
        items = null;
    }

    public String getFullNameLogin() {
        if (FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(AUTH_KEY_FULLNAME) != null) {
            return FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(AUTH_KEY_FULLNAME).toString();
        }
        return "";
    }

    public String login() {
        Users userLogin = null;
        if (username != null && password != null) {
            System.out.print(username);
            userLogin = ejbFacade.getUserlogin(username, hashPassword(password));
        }
        if (userLogin != null) {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
                    AUTH_KEY, userLogin.getUsername());
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
                    AUTH_KEY_FULLNAME, userLogin.getFirstName() + " " + userLogin.getLastName());
            username = "";
            password = "";
            
            return "/faces/admin/messages/List.xhtml";
        } else {
            JsfUtil.addErrorMessage("Username or password not correct.");
            return "/faces/login/Login.xhtml";
        }
    }

    public String logout() {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
                .remove(AUTH_KEY);
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
                .remove(AUTH_KEY_FULLNAME);
        return "/faces/login/Login.xhtml?faces-redirect=true";
    }

    public String hashPassword(String password) {
        String hashword = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(password.getBytes());
            BigInteger hash = new BigInteger(1, md5.digest());
            hashword = hash.toString(16);
        } catch (NoSuchAlgorithmException nsae) {
        }
        return hashword;
    }

    @FacesConverter(forClass = Users.class)
    public static class UsersControllerConverter implements Converter {

        public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
            if (value == null || value.length() == 0) {
                return null;
            }
            UsersController controller = (UsersController) facesContext.getApplication().getELResolver().
                    getValue(facesContext.getELContext(), null, "usersController");
            return controller.ejbFacade.find(getKey(value));
        }

        java.lang.Integer getKey(String value) {
            java.lang.Integer key;
            key = Integer.valueOf(value);
            return key;
        }

        String getStringKey(java.lang.Integer value) {
            StringBuffer sb = new StringBuffer();
            sb.append(value);
            return sb.toString();
        }

        public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
            if (object == null) {
                return null;
            }
            if (object instanceof Users) {
                Users o = (Users) object;
                return getStringKey(o.getUserId());
            } else {
                throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + Users.class.getName());
            }
        }
    }
}
